from abc import ABC, abstractmethod
import inspect

class SVDObject(ABC):
    def __init__(self, name: str = ""):
        self.name = name
        self.father = ""
        self.description = ""
        self.type = "SVDObject"
        self.OutOfValidCheck : list[str] = ["description","EnumeratedValues","groupName","regaccess","fields","headerStructName","derivedFrom","enumDescription",'dim','dimIncrement','dimIndex','interrupt', 'int_name', 'int_description','modifiedWriteValues','writeConstraint','readAction']
        self.boolVaildCheck : list[str] = ["mpuPresent","fpuPresent","vendorSystickConfig"]
        self.numberVaildCheck: list[str] = ["nvicPrioBits","width","size","resetValue","resetMask","addressUnitBits","enumvalue","base_address","offset","lsb","msb"]
    
    @classmethod
    def init_from_dict(cls, params: dict): # 通过传入的参数创建对象
        return cls(**params)
    
    @classmethod
    def gen_inst_from_dict(cls, dic_contains_para: dict): 
        cls_init_parameter = {}
        for para in cls.GetInitParameters():
            if not para in dic_contains_para :
                print(f"[Error][{cls.__name__}] init Parameter[{para}] not in input dic:{dic_contains_para.keys()} ")
                return None
            cls_init_parameter[para] = dic_contains_para[para]
        cls_inst = cls.init_from_dict(cls_init_parameter)
        
        if not cls_inst :
            print(f"[Error][{cls.__name__}]Fail to gen [{cls_init_parameter['name']}] inst!!! \n")
            return None
        
        return cls_inst
    
    @classmethod
    def check_init_paremeters(cls, dic_contains_para: dict)  -> str: 
        return ""
    
    @classmethod
    def GetInitParameters(cls): # 获取__init__方法的签名
        signature = inspect.signature(cls.__init__)
        # 提取参数名称，排除self和father
        params = [param.name for param in signature.parameters.values() if param.name not in ('self', 'father')]
        return params
    
    def ValidCheck(self):
        errcnt = 0
        attributes = vars(self)
        for attribute, value in attributes.items():
            
            # 免检通道
            if attribute in self.OutOfValidCheck :
                if False:
                    print(f"[NOTE][{self.myself()}][{attribute}:{str(value)}] is skipping validation.")
            
            
            # bool 值合法检测通道
            elif attribute in self.boolVaildCheck:
                if str(value).lower() not in ["true", "false"] :
                    errcnt += 1
                    print(f"[Error][{self.myself()}][{attribute}:{str(value)}] is not valid, need a valid value (true or false).")
                else :
                    pass
            
            # 数字非法检测通道
            elif attribute in self.numberVaildCheck:
                value_str = str(value).lower()
                
                # 检查是否是以 "0x" 开头的有效十六进制数
                if value_str.startswith("0x") and all(c in "0123456789abcdefABCDEF" for c in value_str[2:]):
                    pass
                else:
                    # 检查是否是整数
                    try:
                        int_value = int(value_str)  # 尝试将字符串转换为整数
                        if int_value < 0:
                            errcnt += 1
                            print(f"[Error][{self.myself()}][{attribute}:{str(value)}] is not valid, need a valid value (0 or positive unsigned int).")
                    except ValueError:
                        errcnt += 1
                        print(f"[Error][{self.myself()}][{attribute}:{str(value)}] is not valid, need a valid value (int or hex starting with 0x).")
                            
            # 字符串非空检测通道
            elif not value :
                errcnt += 1
                print(f"[Error][{self.myself()}][{attribute}:{str(value)}] is not valid, need a valid value.")
            else :
                pass
                
        return errcnt

    def TabsString(self, n: int) -> str:
        return ' ' * (n * 4)
        
    def __repr__(self):
        return f"SVDObject(name={self.name}, description={self.description}, value={self.value})"

    def GetAttributeCSVString(self) -> str:
        csvStr = f"Class : {[self.__class__.__name__]},\n"
        for attribute, value in vars(self).items():
            csvStr += f"{attribute},\n"
        csvStr += f",\n"
        csvStr += f",\n"
        return csvStr
    
    def myself(self):
        return f"{self.father}>{self.type}:{self.name}"

    @abstractmethod
    def toString(self,tablevel) -> str:
        xml_output = (
            f"{self.TabsString(tablevel)}<SVDObject>I AM GOD</SVDObject>\n"
        )
        
        return xml_output
    
        
    @staticmethod
    @abstractmethod
    def GetTestObject():
        return SVDObject("GOD")
        
    @staticmethod
    @abstractmethod
    def TestString():
        testObject = SVDObject.GetTestObject()
        print(testObject.toString(2))    
    